using System;
using System.Data;
using NHibernate.UserTypes;
using Sedna.Domain;
using NHibernate;
using NHibernate.SqlTypes;

namespace Sedna.Core.Persistence
{
	/// <summary>
	/// Hibernate infrastructure class that maps <see cref="Weight"/> domain value to a NUMERIC database column.
	/// Note, this mapping assumens that all Weight values are in OZ (Troy Ounces) thus, making no
	/// conversion or any other check logic. Please use WeightType (that is to be created in future) to map to a multy-UOM database.
	/// 
	/// This mapping NEVER stores and returns Nulls from the DB. I.e. Weight.Default is converted to 0 (zero)
	/// and in case of a NULL in a database, it is converted into 0Oz (zero Oz)
	/// </summary>
	public class WeightOzType : IUserType
	{
		public object NullSafeGet(IDataReader rs, string[] names, object owner)
		{
			int index = rs.GetOrdinal(names[0]);
			return rs.IsDBNull(index)
				? Weight.Default
				: Weight.CreateFromFactoredAmount(Convert.ToInt64(NHibernateUtil.Int64.Get(rs, names[0])));
		}

		public void NullSafeSet(IDbCommand cmd, object value, int index)
		{
			Weight weight = value as Weight;
			if(weight != null)
			{
				NHibernateUtil.Int64.Set(cmd, weight.Amount, index);
			}
			else
			{
				//assume that a value is either a long or can be cast thereto
				NHibernateUtil.Int64.Set(cmd, value!=null?value:0, index);
			}
		}

		public object DeepCopy(object value)
		{
			return value;//Weight is immutable
		}

		public SqlType[] SqlTypes
		{
			get { return new SqlType[]{NHibernateUtil.Int64.SqlType}; }
		}

		public Type ReturnedType
		{
			get { return typeof(Weight); }
		}

		public bool IsMutable
		{
			get { return false; }
		}

		public new bool Equals( object x, object y )
		{
			return x==null?y==null:x.Equals(y);
		}
        public object Disassemble(object value)
        {
            return value;
        }

        public object Assemble(object cached, Object owner)
        {
            return cached;
        }

        public object Replace(object original, object target, object owner)
        {
            return original;
        }

        public int GetHashCode(Object x)
        {
            return x.GetHashCode();
        }

	}
}
